/*******************************************************************************

  Pilot Intelligence Library
    http://www.pilotintelligence.com/

  ----------------------------------------------------------------------------

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.

*******************************************************************************/


#include "base/time/Time.h"

#include "MissionData_Transfer.h"

using namespace std;
using namespace pi;


MissionData_Transfer::MissionData_Transfer()
{
    pi::Thread::setName("MissionData_Transfer");

    m_bOpened = 0;
    m_isServer = 1;
}

MissionData_Transfer::~MissionData_Transfer()
{
    if( m_bOpened ) {
        m_socket.close();
        pi::Thread::stop();
    }

    m_bOpened = 0;
    m_isServer = 1;
}

void MissionData_Transfer::threadFunc()
{
    int             msgLen = sizeof(MissionData_Simp)*2;
    uint8_t         *msgBuf;
    int             ret;

    msgBuf = new uint8_t[msgLen];

    // loop for ever
    while( !shouldStop() ) {
        ret = m_socket.recv(msgBuf, msgLen);
        if( ret <= 0 ) {
            tm_sleep(2);
            continue;
        }

        MissionData_Simp mis;
        if( ret == sizeof(MissionData_Simp) ) {
            memcpy(&mis, msgBuf, sizeof(MissionData_Simp));

            ScopedMutex m(m_mutex);
            m_misQueue.push_back(mis);
        }
    }

    delete [] msgBuf;
}

int MissionData_Transfer::begin(const std::string &addr, int port, int isServer)
{
    if( m_bOpened ) {
        dbg_pe("socket is open. Please close first!");
        return -1;
    }

    // FIXME: server to send mission, client to recieve mission
    //        this usage is inverse to socket
    m_isServer = isServer;
    if( m_isServer ) {
        if( m_socket.startClient(addr, port, SOCKET_UDP_MULTICAST) != 0 ) {
            dbg_pe("start server failed! (%s:%d SOCKET_UDP_MULTICAST)", addr.c_str(), port);
            return -2;
        }
    } else {
        if( m_socket.startServer(addr, port, SOCKET_UDP_MULTICAST) != 0 ) {
            dbg_pe("start client failed! (%s:%d SOCKET_UDP_MULTICAST)", addr.c_str(), port);
            return -2;
        }

        // start receiving thread
        start(NULL);
    }

    m_bOpened = 1;

    return 0;
}

void MissionData_Transfer::stop(void)
{
    if( !m_bOpened ) return;

    // stop receiving thread
    if( !m_isServer ) {
        pi::Thread::stop();
        tryJoin(10);
    }

    // close socket
    m_socket.close();

    m_bOpened = 0;
}


int MissionData_Transfer::sendMission(MissionData_Simp *m)
{
    if( m_isServer ) {
        return m_socket.send((uint8_t*) m, sizeof(MissionData_Simp));
    } else {
        dbg_pe("Current mode is not Server!");
        return -1;
    }
}

int MissionData_Transfer::recvMission(MissionData_Simp *m)
{
    if( m_isServer ) {
        dbg_pt("Current mode is not Client!");
        return -1;
    } else {
        ScopedMutex mux(m_mutex);

        if( m_misQueue.size() > 0 ) {
            MissionData_Simp &mis = *m;

            mis = m_misQueue.front();
            m_misQueue.pop_front();

            return 0;
        } else {
            return -2;
        }
    }
}
